#include "Roi.h"
#include "Fou.h"
#include "Tour.h"
#include "Dame.h"

#include <string>
#include <typeinfo>
using namespace std;
using std::string;

string Roi::nom("Roi");

Roi::Roi(Echiquier * E, Position P, bool couleur, bool mv): Piece(E,P,couleur), deplace(mv)
{
	object = new RoiGL (this, couleur) ;
}
Roi::~Roi(){
	if (object){
		delete object;
		object = NULL ;
	}
}
bool Roi::estDeplace() const { return deplace; }

char Roi::rendu() const
{
	return (c ? 'R' : 'r');
}

const string& Roi::toString()const
{
	return nom;
}

void Roi::majAtk()
{
    atk.clear();
    if(p.getL()-1>=0)
    {
        atk.push_back(Position(p.getL()-1,p.getC()));
        if(p.getC()-1>=0)
            atk.push_back(Position(p.getL()-1,p.getC()-1));
        if(p.getC()+1<8)
            atk.push_back(Position(p.getL()-1,p.getC()+1));
    }
    if(p.getC()-1>=0)
    {
        atk.push_back(Position(p.getL(),p.getC()-1));
    }
    if(p.getL()+1<8)
    {
        atk.push_back(Position(p.getL()+1,p.getC()));
        if(p.getC()-1>=0)
            atk.push_back(Position(p.getL()+1,p.getC()-1));
        if(p.getC()+1<8)
            atk.push_back(Position(p.getL()+1,p.getC()+1));
    }
    if(p.getC()+1<8)
        atk.push_back(Position(p.getL(),p.getC()+1));
}

bool Roi::roquePossible(bool type)const
{
	return (type ? grq : prq);
}

void Roi::roque(bool type)
{
	Piece* ppiece;
	Tour* ptour;
	if(c)	// Blanc
		if(!type)	// Petit Roque
		{
			ppiece = e->getPiece(Position(7,0));
			if(typeid(*ppiece) == typeid(Tour))
			{
				ptour = dynamic_cast<Tour*>(ppiece);
				ptour->roque(this, type);
			}
		}
		else		// Grand Roque
		{
			ppiece = e->getPiece(Position(7,7));
			if(typeid(*ppiece) == typeid(Tour))
			{
				ptour = dynamic_cast<Tour*>(ppiece);
				ptour->roque(this, type);
			}
		}
		else	//Noir
			if(!type)	// Petit Roque
			{
				ppiece = e->getPiece(Position(0,0));
				if(typeid(*ppiece) == typeid(Tour))
				{
					ptour = dynamic_cast<Tour*>(ppiece);
					ptour->roque(this, type);
				}
			}
			else		// Grand Roque
			{
				ppiece = e->getPiece(Position(0,7));
				if(typeid(*ppiece) == typeid(Tour))
				{
					ptour = dynamic_cast<Tour*>(ppiece);
					ptour->roque(this, type);
				}
			}
}

void Roi::deplacement(const Position& pos) throw (std::invalid_argument)
{
	std::cout << "################################" << std::endl;
	Piece::deplacement(pos);
	
	Position prp(c ? Position(7,1) : Position(0,1));
	Position grp(c ? Position(7,5) : Position(0,5));
	
	std::cout << __PRETTY_FUNCTION__ << (c ? " BLANC" : " NOIR") << std::endl;
	std::cout << "Grand roque : " << (grq ? "oui" : "non" ) << std::endl;
	std::cout << "Petit roque : " << (prq ? "oui" : "non" ) << std::endl;
	std::cout << "DÈplacement grand roque : " << (pos == grp ? "oui" : "non" ) << std::endl;
	std::cout << "DÈplacement petit roque : " << (pos == prp ? "oui" : "non" ) << std::endl;
	
	if(grq && pos == grp)
		roque(GROQUE);
	else if(prq && pos == prp)
		roque(PROQUE);
	
	deplace = true;
}

void Roi::majDeplacements()
{
    cloue = false;
    grq = false;
    prq = false;
	dep.clear(); // remise ‡ zÈro de sa liste de dÈplacement
	Piece* temp;
	
	if(p.getL()+1 < 8)
	{
		if (p.getC()+1 < 8 && (((temp = e->getPiece(Position(p.getL()+1,p.getC()+1))) != NULL && temp->estBlanc() != c) || temp == NULL))
			if(!e->caseAttaquee(Position(p.getL()+1,p.getC()+1), !c))
				dep.push_back(Position(p.getL()+1,p.getC()+1));
		
		if (p.getC()-1 >= 0 && (((temp = e->getPiece(Position(p.getL()+1,p.getC()-1))) != NULL && temp->estBlanc() != c) || temp == NULL))
			if(!e->caseAttaquee(Position(p.getL()+1,p.getC()-1), !c))
				dep.push_back(Position(p.getL()+1,p.getC()-1));
		
		if (((temp = e->getPiece(Position(p.getL()+1,p.getC()))) != NULL && temp->estBlanc() != c) || temp == NULL)
			if(!e->caseAttaquee(Position(p.getL()+1,p.getC()), !c))
				dep.push_back(Position(p.getL()+1,p.getC()));
	}
	if(p.getL()-1 >= 0)
	{		
		if (p.getC()+1 < 8 && (((temp = e->getPiece(Position(p.getL()-1,p.getC()+1))) != NULL && temp->estBlanc() != c) || temp == NULL))
			if(!e->caseAttaquee(Position(p.getL()-1,p.getC()+1),!c))
				dep.push_back(Position(p.getL()-1,p.getC()+1));
		
		if (p.getC()-1 >= 0 && (((temp = e->getPiece(Position(p.getL()-1,p.getC()-1))) != NULL && temp->estBlanc() != c) || temp == NULL))
			if(!e->caseAttaquee(Position(p.getL()-1,p.getC()-1), !c))
				dep.push_back(Position(p.getL()-1,p.getC()-1));
		
		if (((temp = e->getPiece(Position(p.getL()-1,p.getC()))) != NULL && temp->estBlanc() != c) || temp == NULL)
			if(!e->caseAttaquee(Position(p.getL()-1,p.getC()), !c))
				dep.push_back(Position(p.getL()-1,p.getC()));
	}
	
	if (p.getC()+1 < 8 && (((temp = e->getPiece(Position(p.getL(),p.getC()+1))) != NULL && temp->estBlanc() != c) || temp == NULL))
		if(!e->caseAttaquee(Position(p.getL(),p.getC()+1), !c))
			dep.push_back(Position(p.getL(),p.getC()+1));
	
	if (p.getC()-1 >= 0 && (((temp = e->getPiece(Position(p.getL(),p.getC()-1))) != NULL && temp->estBlanc() != c) || temp == NULL))
		if(!e->caseAttaquee(Position(p.getL(),p.getC()-1), !c))
			dep.push_back(Position(p.getL(),p.getC()-1));
	
	// Tests des Roques
	if(!deplace && !pAtk.size())
	{
		// Si le roi est Blanc
		if(c)
		{
			std::cout << "rjghuretgiopherglp" << std::endl;
			Piece *p1(e->getPiece(Position(7,0))), *p2(e->getPiece(Position(7,7)));
			Tour *t1(p1 && typeid(*p1) == typeid(Tour) ? dynamic_cast<Tour*>(p1) : NULL);
			Tour *t2(p2 && typeid(*p2) == typeid(Tour) ? dynamic_cast<Tour*>(p2) : NULL);
			
			std::cout << "TOUR1 : " << t1 << std::endl;
			std::cout << "TOUR2 : " << t2 << std::endl;
			
			if(p == Position(7,3))
			{
				std::cout << "###**" << std::endl;
				std::cout << "roi OK pour test." << std::endl;
				// Test du Petit Roque
				if(	t1 &&
				   !t1->estDeplace() &&
				   t1->estBlanc() && 
				   !e->caseAttaquee(Position(7,1), !c) && 
				   !e->getPiece(Position(7,1)) && 
				   !e->caseAttaquee(Position(7,2), !c) && 
				   !e->getPiece(Position(7,2)))
				{
					dep.push_back(Position(7,1));
					prq = true;
				}
				
				// Test du Grand Roque
				if(	t2 &&
				   !t2->estDeplace() &&
				   t2->estBlanc() &&
				   !e->caseAttaquee(Position(7,4), !c) && 
				   !e->getPiece(Position(7,4)) && 
				   !e->caseAttaquee(Position(7,5), !c) && 
				   !e->getPiece(Position(7,5)) && 
				   !e->caseAttaquee(Position(7,6), !c) && 
				   !e->getPiece(Position(7,6)))
				{
					dep.push_back(Position(7,5));
					grq = true;
				}
			}
		}
		else // Roi noir
		{
			Piece *p1(e->getPiece(Position(0,0))), *p2(e->getPiece(Position(0,7)));
			Tour *t1(p1 && typeid(*p1) == typeid(Tour) ? dynamic_cast<Tour*>(p1) : NULL);
			Tour *t2(p2 && typeid(*p2) == typeid(Tour) ? dynamic_cast<Tour*>(p2) : NULL);
			
			if(p == Position(0,3))
			{
				// Test du Petit Roque
				if(	t1 &&
				   !t1->estDeplace() &&
				   !t1->estBlanc() && 
				   !e->caseAttaquee(Position(0,1), !c) && 
				   !e->getPiece(Position(0,1)) && 
				   !e->caseAttaquee(Position(0,2), !c) && 
				   !e->getPiece(Position(0,2)))
				{
					dep.push_back(Position(0,1));
					prq = true;
				}
				
				// Test du Grand Roque
				if(	t2 &&
				   !t2->estDeplace() &&
				   !t2->estBlanc() && 
				   !e->caseAttaquee(Position(0,4), !c) && 
				   !e->getPiece(Position(0,4)) &&
				   !e->caseAttaquee(Position(0,5), !c) && 
				   !e->getPiece(Position(0,5)) && 
				   !e->caseAttaquee(Position(0,6), !c) && 
				   !e->getPiece(Position(0,6)))
				{
					dep.push_back(Position(0,5));
					grq = true;
				}
			}
		}
	}
}
void Roi::majppAtk()
{
	Piece *piece, *piece2;
	Position tmp(p);
	bool cont(true),found(false),cond(false);
	std::list<Piece*> pCloues;
	
	ppAtk.clear();
	
	while(--tmp.getC() >= 0 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	cont = true; found = false; cond = false; tmp = p;
	while(++tmp.getC() < 8 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	cont = true; found = false; cond = false; tmp = p;
	while(--tmp.getL() >= 0 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	cont = true; found = false; cond = false; tmp = p;
	while(++tmp.getL() < 8 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Tour)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	cont = true; found = false; cond = false; tmp = p;
	while(--tmp.getC() >= 0 && --tmp.getL() >= 0 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	cont = true; found = false; cond = false; tmp = p;
	while(--tmp.getC() >= 0 && ++tmp.getL() < 8 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	cont = true; found = false; cond = false; tmp = p;
	while(++tmp.getC() < 8 && --tmp.getL() >= 0 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	cont = true; found = false; cond = false; tmp = p;
	while(++tmp.getC() < 8 && ++tmp.getL() < 8 && cont && (!found || found == cond))
	{
		if(!found)
		{
			if(found = (piece = e->getPiece(tmp)))
				cond = (c == piece->estBlanc());
		}
		else if((piece2 = e->getPiece(tmp)))
		{
			cont = false;
			if(piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
				ppAtk.push_back(piece2);
		}
	}
	
	if(!cont && piece2->estBlanc() != c && ((typeid(*piece2) == typeid(Fou)) || (typeid(*piece2) == typeid(Dame))))
		pCloues.push_back(piece);
	
	// ici on cloue les pieces
	for(std::list<Piece*>::iterator i(pCloues.begin()); i != pCloues.end(); i++)
	{
		(*i)->setCloue(true);
		std::cout << "cloue !" << std::endl;
	}
}

std::list<Piece*>& Roi::getppAtk()
{
	return ppAtk;
}

Piece* Roi::clone(Echiquier* ne) const
{
	Piece* clone = new Roi(ne,p,c,deplace);
	clone->getDep() = dep;
	clone->getAtk() = atk;
	clone->getpAtk() = pAtk;
	clone->getpDef() = pDef;
	return clone;
}
